/*!  \file  RandomGeneraor.h
 *	  \brief  
 * 
 *   \details   details
 *   \author    Yordan Madzhunkov German Research School for Simulation Sciences GmbH
 *   \version   1.0
 *   \date      05/12/2013 10:09:52 AM
 *   \copyright GNU Public License.
 */
#pragma once
#include "macros.h"
class RandomGenerator {
public:
	RandomGenerator(): the_x(0), stateData(0), have_x(false){};
	virtual ~RandomGenerator();
	static RandomGenerator* defaultGenerator (const unsigned int someSeed=1234);
	
	virtual void setSeed(const unsigned int N);
	virtual void setSeed(void * stateDataPtr);

	virtual size_t stateSize() const = 0;
	virtual double getUniform() = 0; // returns random number from in [0.0,1.0)


	size_t stateSizeInMem() { 
		size_t s = stateSize();
		size_t b = sizeof(unsigned int);
		return (s/b) * b + (s % b != 0) * b;
	}
	virtual void fillUniform(const unsigned int N, double * __restrict__ d);

	double getUniform(const double a, const double b) {
		return a + getUniform() * (b - a);}
   inline double getGaussian() {
        if( have_x ) { have_x = false; return the_x; }
        double r = sqrt(-2*log(1-getUniform()));
        double cphi, sphi; getAzimuth(cphi,sphi);
        have_x = true; the_x = r*sphi; return r*cphi;
    };
   inline double getGaussian(const double mean, const double sigma) {
		return mean + getGaussian() * sigma;
	}
    inline void getAzimuth(double & cphi, double & sphi) {
        double phi = 2 * M_PI * getUniform();
        cphi = cos(phi); sphi = sin(phi);
    };
protected:
	DISALLOW_COPY_AND_ASSIGN(RandomGenerator);
	double the_x;
	void * stateData;	
	bool have_x;
};

